<?php

/**
 * 类名：IntConvert
 * 作者：mqycn
 * 博客：http://www.miaoqiyuan.cn
 * 源码：https://gitee.com/mqycn/IntConvert
 * 说明：数字字符串互换类，常见的应用场景比如邀请码
 */

class IntConvert {

	/**
	 * KeyMap 在初始时，建议重新生成一下
	 */
	static private $keyMap = [
		'51GUM2IB3SNEKAWHXL7DFZRV69O4CY8Q',
		'ULQ5KH4GSF8IA6OENRXYZB729W1MDV3C',
		'HWFKE571694Y2UCM3RNDSIAZ8BVGLOXQ',
		'KMQ8U1X5CB4HYRVL6O27DGI3FWAES9ZN',
		'B2A5I74MVERZWYL9XN3CGDSF1QUOH6K8',
		'MSCRAD75V1LW82H3B6ZYEFX4UQOIN9KG',
		'FXV1QM7HS5LEKWGOACR6IYN392DUZB48',
		'MDVU72YN5AFBW4ISRZ19EOCL38GHKQX6',
		'DXQBC5UK4ENZHIV27O1G3RMAL6F9WYS8',
		'Z9VFMHC438OEUKA1Y57QISLNG2DXR6BW',
		'RLBHOQ5N8IFXME246ZCSUWKD7Y91V3GA',
		'KOGNZDY2B4I3UQ9FRWVS75H8L16AECXM',
		'C56INYM2DWBHO7VZ1U3LS849ERXKGAFQ',
		'C5RN3LUS46Y1EQMD8AOIK972BHZWGFXV',
		'OL7H8X3EY6QDCK42B59SIVWN1GFRUAZM',
		'Z5DLH8W9ABXUVE74YQ21G6F3KNCRMIOS',
	];

	/**
	 * 生成随机Key
	 */
	static public function randomKey() {

		header('content-type: text/text; charset=utf-8');
		echo "	#请复制到 IntConvert 头部\n";
		echo "	static private $" . "keyMap = [\n";

		for ($i = 0; $i < 16; $i++) {
			$keys = self::$keyMap[0];
			$keys_new = '';
			$word = '';

			$len = strlen($keys);
			while ($len > 0) {
				$word = substr($keys, rand(0, $len - 1), 1);
				$keys = str_replace($word, '', $keys);
				$keys_new .= $word;
				$len = strlen($keys);
			}
			echo "		'$keys_new',\n";
		}
		echo "	];\n";
		die();
	}

	/**
	 * 将数字编码为字符串
	 */
	static public function toString($num = 0) {

		// 对传入的数字，取hash的第一位
		$hash = self::getHash($num);

		// 根据Hash，选择不同的字典
		$keymap = self::getKeyMap($hash);

		// 数字转二进制
		$map = self::fixBin(decbin($num));

		// 如果不足10位，前面自动补全对应个数的0
		$len = strlen($map);
		if ($len < 10) {
			$map = substr('00000000000000000000', 0, (10 - $len)) . $map;
		}

		// 按5个一组，编码成数字，根据KeyMap加密
		$keys = '';
		$len = strlen($map);
		for ($index = 0; $index < strlen($map); $index += 5) {
			$keys .= substr($keymap, bindec(substr($map, $index, 5)), 1);
		}

		return $hash . $keys;
	}

	/**
	 * 将字符串编码为数字
	 */
	static public function toInt($str = '') {

		//根据生成规则，最小长度为3
		if (strlen($str) < 3) {
			return false;
		}
		$hash = substr($str, 0, 1);
		$keys = substr($str, 1);

		// 根据Hash，选择不同的字典
		$keymap = self::getKeyMap($hash);

		$bin = '';
		// 根据字典，依次 index，并转换为二进制
		for ($i = 0; $i < strlen($keys); $i++) {
			for ($index = 0; $index < strlen($keymap); $index++) {
				if (strtoupper(substr($keys, $i, 1)) === substr($keymap, $index, 1)) {
					$bin .= self::fixBin(decbin($index));
				}
			}
		}

		// 二进制转换为数字
		$num = bindec($bin);

		if (self::getHash($num) === $hash) {
			return $num;
		} else {
			return false;
		}

	}

	/**
	 * 根据Hash取字典
	 */
	static private function getKeyMap($hash = 'A') {
		return self::$keyMap[hexdec($hash)];
	}

	/**
	 * 不足5位的二进制，自动补全二进制位数
	 */
	static private function fixBin($bin = '110') {
		$len = strlen($bin);
		if ($len % 5 != 0) {
			$bin = substr('00000', 0, (5 - $len % 5)) . $bin;
		}
		return $bin;
	}

	/**
	 * 对数字进行Hash
	 */
	static private function getHash($num = 0) {
		return strtoupper(substr(md5(self::getKeyMap(0) . $num), 1, 1));
	}
}